﻿//-----------------------------------------------------------------------
// <copyright file="GetValue.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Steve Overall</author>
// <email>v-stevov</email>
// <date>2005-04-15</date>
// <summary>Gets a value from an element ot attribute in an XML file.</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.XmlFile
{
	#region Using directives

	using System;
	using System.Collections.Generic;
	using System.Text;
	using System.Xml;

	using Microsoft.Build.Framework;
	using Microsoft.Build.Tasks;
	using Microsoft.Build.Utilities;

	using Microsoft.Sdc.Tasks;

	#endregion

	#region class comments
	/// <summary>
	/// Gets a value of an element or attribute matching the passed XPath
	/// expression in the specified XML File.
	/// Will fail if no match found for the specified XPath expression.
	/// </summary>
	/// <remarks>
	/// <code>
	/// <![CDATA[<XmlFile.GetValue Path="path" XPath="xpath" Namespaces="namespaces" IgnoreNoMatchFailure="ignoreNoMatchFailure"/>]]>
	/// </code>
	/// <para>where:</para>
	/// <para><i>Path (Required)</i></para>
	/// <para>The path of the XML file to read.</para>
	/// <para><i>XPath (Required)</i></para>
	/// <para>The XPath expression to evaluate to find the element or attribute whose value we want.</para>
	/// <para><i>Namespaces</i></para>
	/// <para>
	/// Optional TaskItems array detailing each of the namespace declarations required to read/maintain the target document.
	/// Each TaskItem should have 2 elements &lt;Prefix&gt; and &lt;Uri&gt;.
	/// </para>
	/// <para><i>Value (Output)</i></para>
	/// <para>The value of the single node matching the XPath expression.</para>
	/// <para><i>IgnoreNoMatchFailure</i></para>
	/// <para>If set to true, no Exception will be thrown if no matches made for the supplied XPath.  Defaults to false.</para>
	/// </remarks>
	/// <example>
	/// <code><![CDATA[
	/// <Project>
	///     <Target Name="Test" >
	///         <XmlFile.GetValue 
	///					Path="c:\app.config"
	///					XPath="/configuration/appSettings/add[@key='myKey']/@value"
	///					Namespaces="@(ConfigNamespaces)">
	///				<Output TaskParameter="Value" Property="appSettings.myKey.value"/>
	///			</XmlFile.GetValue>
	///     </Target>
	/// </Project>
	/// ]]></code>    
	/// </example>
	#endregion
	public class GetValue : BaseXmlFileTask
	{
		#region private declarations
		private string		_value					= String.Empty;
		private bool		_ignoreNoMatchFailure	= false;
		#endregion

		#region constructors
		/// <summary>
		/// Create a new ChangeValue.
		/// </summary>
		public GetValue() : base()
		{
		}
		#endregion

		#region override of InternalExecute
		/// <summary>
		/// Carry out this task's action.
		/// </summary>
		protected override void InternalExecute()
		{
			//	Load the XML file.
			XmlDocument xmlDoc = this.OpenXmlFile( this.Path );
			XmlNamespaceManager nsMgr = this.GetNamespaceManagerForDoc( xmlDoc, this.Namespaces );

			//	Run the XPath Expression against the XML file.
			//	Get the list of matching elements.
			XmlNode node = xmlDoc.SelectSingleNode( this.XPath, nsMgr );
			if ( node != null )
			{
				switch( node.NodeType )
				{
					case XmlNodeType.Element:
						_value = node.InnerText;
						break;

					case XmlNodeType.Attribute:
						_value = node.Value;
						break;

					default:
						throw new TaskException( Log.FormatResourceString("XmlFile.UnsupportedNodeType.Exception", node.NodeType) );
				}

				Log.LogMessageFromResources( "XmlFile.GetValue.Success", this.FileName, this.XPath, _value );
			}
			else
			{
				if ( _ignoreNoMatchFailure )
					Log.LogWarningFromResources( "XmlFile.NoMatch.Warning", this.FileName, this.XPath );
				else
					throw new TaskException( Log.FormatResourceString( "XmlFile.NoMatch.Exception", this.XPath ) );
			}
		}
		#endregion

		#region public Properties
		/// <summary>
		/// If set to true, no Exception will be thrown if no matches made for the supplied XPath.  Defaults to false.
		/// </summary>
		/// <value>If set to true, no Exception will be thrown if no matches made for the supplied XPath.  Defaults to false.</value>
		public bool IgnoreNoMatchFailure
		{
			get { return _ignoreNoMatchFailure; }
			set { _ignoreNoMatchFailure = value; }
		}

		/// <summary>
		/// The value of the requested element or attribute.
		/// </summary>
		/// <value>The value of the requested element or attribute.</value>
		[Output]
		public string Value
		{
			get { return _value; }
		}
		#endregion
	}
}
